<template>
  <div
    class="meng-editor"
    :style="{ height: height, width: width }"
    :ref="'mengEditor'+editIndex"
  >
    <div class="meng-editor-header">
      <ul class="meng-editor-header-ul">
        <li
          v-for="(item, index) in headerConfig"
          :key="index"
          :class="{
            'meng-editor-header-li-selected': index === selectedIndex && active,
          }"
          class="header-ul-li"
          @click="showItem(item, index, $event)"
        >
          <i
            :class="item.icon"
            onmousedown="event.preventDefault();"
            :title="item.title"
          >
          </i>
        </li>
      </ul>
    </div>
    <div class="meng-editor-body" @click="resetSelect">
      <div
        id="text_area"
        class="meng-editor-body-content"
        :contenteditable="!disabled"
        v-focus
        ref="richEdit"
        @input="changeInput"
      ></div>
    </div>
    <context-menu></context-menu>
    <div class="meng-editor-popup" v-show="show" ref="mengEditorPopup">
      <component
        :is="currentComponent"
        :range="range"
        :uploadMethod="uploadMethod"
        :uploadResponse="uploadResponse"
        :currentSelection="currentSelection"
        :editIndex="editIndex"
        @selectmenu="selectMenu"
      ></component>
    </div>
  </div>
</template>

<script>
import './css/font-awesome.min.css'
import { configList } from './headerConfig'
import headerList from './components/header-list/index'
import tableBox from './components/table/index'
import imageBox from './components/image-box/index'
import fontList from './components/font-list/index'
import mixin from './mixins/index'
import contextMenu from './contextMenu/ContextMenu'
import linkBox from './components/link-box/index'
export default {
  name: 'mt-editor',
  components: { headerList, tableBox, imageBox, fontList, contextMenu, linkBox },
  mixins: [mixin],
  props: {
    width: {
      type: String,
      default: '100%'
    },
    height: {
      type: String,
      default: '500px'
    },
    config: {
      type: Object,
      default: () => { return {} }
    },
    value: {
      type: String,
      default: ``
    },
    uploadMethod: {
      type: Function,
      default: () => { return () => { } }
    },
    uploadResponse: {
      type: Array
    },
    editIndex: {
      type: Number,
      default: 0
    },
    disabled: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
      show: false,
      selectedIndex: '',
      currentComponent: '',
      // 光标所在位置信息
      range: {},
      currentSelection: {},//保留上次光标所在的位置
      active: false,
      isInit: true
    }
  },
  watch: {
    value(){
      // let richEdit = this.$refs['richEdit'];
      // richEdit.innerHTML = val
      // this.initEditor();
    },
    range(){
      console.log('range的值发生变化了')
    }
  },
  directives: {
    focus: {
      inserted: function (el) {
        el.focus()
      }
    }
  },
  computed: {
    headerConfig () {
      /*
          用户配置比较和对象比较
      */
      let configKeys = Object.keys(this.config)
      if (configKeys.length) {
        let arr = [];
        for (let key in this.config) {
          let item = configList[key]
          if (item) {
            arr.push(item)
          }
        }
        return arr;
      }
      return configList
    }
  },
  created () {

  },
  mounted () {
    this.initEditor();
    const editableElement = this.$refs.richEdit;
    editableElement.addEventListener('blur', this.handleBlur);
  },
  methods: {
    handleBlur(){
      console.log('光标消失')
      this.backupRange('输入框失去焦点')
    },
    resetSelect () {
      this.show = false
      if (this.currentComponent) {
        this.active = false
      }
    },
    // 初始化富文本编辑器内容
    initEditor () {
      let richEdit = this.$refs['richEdit'];
      if (this.value) {
        richEdit.innerHTML = this.value
      } else {
        richEdit.innerHTML = `<div><br></div> `;
      }
    },
    showItem (item, index, ev) {
      /*
          判断配置里是否有组件，如果有则显示弹窗组件
      */
      if (item.component) {
        this.currentComponent = item.component
      } else {
        this.currentComponent = ''
      }
      // 判断选中的index和上次的是否一样，如果是一样，就关闭弹框
      if (this.selectedIndex === index) {
        this.show = !this.show;
        this.active = !this.active
      } else {
        this.show = true;
        this.active = true
      }
      this.selectedIndex = index;
       // 判断是否布局按钮
      if (item.layout) {
          this.setLayout()
          return
      }
      // 控制弹窗,如果没有弹窗，表示直接执行格式化功能
      if (!item.popup) {
        this.show = false;
        this.execCommand(item.command, false, null)
        return;
      }
      // 获取富文本的最外层个，用于控制各种弹窗的位置不要超过服务本的边界
      let mengEditor = this.$refs['mengEditor'+this.editIndex]
      // 距离顶部的位置
      // let offsetTop = mengEditor.offsetTop;
      // 距离左边的位置
      let offsetLeft = mengEditor.offsetLeft;
      // 富文本右边框距离左边的距离
      let borderRight = offsetLeft + mengEditor.clientWidth;
      /*
          鼠标的位置，大于左边边距，小于右边距就表示在文本框内
      */
      let position = this.getTargetPosition(ev)
      /*
          如果接近左边界，则弹框显示在边界右边
          如果接近右边界，则弹框显示在边界左边
      */
      if (position.x > offsetLeft && position.x < borderRight) {
        // 如果靠近右边框-100个像素，就让弹框显示在左边
        if (position.x > borderRight - 100) {
          this.setPopupPosition(borderRight - 100, position.y + 12)
        } else {
          this.setPopupPosition(position.x, position.y + 12)
        }
      }
    },
    // 设置布局
    setLayout () {
      if (!this.currentSelection.endContainer) {return}
      let textData = this.currentSelection.endContainer.data
      let preText = textData.slice(0,this.currentSelection.endOffset)
      let nextText = textData.slice(this.currentSelection.endOffset, -1)
      let parentElement = this.currentSelection.endContainer.parentElement
      parentElement.innerHTML = ''
      parentElement.className = "flex-row"
      let preTextNode = document.createElement('div')
      preTextNode.innerText = preText
      let nextTextNode = document.createElement('div')
      nextTextNode.innerText = nextText
      parentElement.appendChild(preTextNode)
      parentElement.appendChild(nextTextNode)
      // 获取光标所在行的位置，以及所在行的内容，进行截取
    },
    setPopupPosition (x, y) {
      let mengEditorPopup = this.$refs['mengEditorPopup'];
      mengEditorPopup.style.left = x + 'px';
      // y轴应该是点击的元素
      mengEditorPopup.style.top = (y + 10) + 'px'
    },
    getTargetPosition (ev) {
      var event = ev || window.event;
      let target = event.target;
      // let offsetTop = target.offsetTop;
      let offsetLeft = target.offsetLeft;
      let parentOffsetTop = target.parentElement.offsetTop + target.parentElement.clientHeight / 2 - 2;
      return { x: offsetLeft, y: parentOffsetTop }
    },
    getMousePosition (ev) {
      var posX = 0, posY = 0;
      var event = ev || window.event;
      if (event.pageX || event.pageY) {
        posX = event.pageX;
        posY = event.pageY;
      } else if (event.clientX || event.clientY) {
        posX = event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft;
        posY = event.clientY + document.documentElement.scrollTop + document.body.scrollTop;
      }
      return { x: posX, y: posY }
    },
    /*
        当内容发生变化的时候，记录光标所在的位置
    */
    backupRange () {
      let selection = window.getSelection();
      let range = selection.getRangeAt(0);
      this.range = range;
      this.currentSelection = {
        "startContainer": range.startContainer,
        "startOffset": range.startOffset,
        "endContainer": range.endContainer,
        "endOffset": range.endOffset
      }
    },
    handleClose () {
      this.show = false
      this.currentComponent = ''
      let richEdit = this.$refs['richEdit']
      let value = richEdit.innerHTML
      this.$emit('input', value)
    },
    changeInput ($event) {
      console.log('文本内容发生变化')
      //  let richEdit = this.$refs['richEdit']
      let value = $event.target.innerHTML
      this.$emit('input', value)
    },
    selectMenu () {
      let richEdit = this.$refs['richEdit']
      let value = richEdit.innerHTML
      this.$emit('input', value)
    }
  }
}
</script>

<style >
.meng-editor {
  width: 100%;
  min-height: 200px;
  border: 1px solid lightgray;
  display: flex;
  flex-direction: column;
}
.meng-editor * {
  margin: 0;
  padding: 0;
}
.meng-editor-header {
  width: 100%;
  min-height: 40px;
  background-color: white;
  border-bottom: 1px solid lightgray;
  flex-shrink: 0;
  list-style: none;
}
.meng-editor-body {
  width: 100%;
  flex-grow: 1;
  max-height: calc(100% - 40px);
  background: white;
  overflow: auto;
}
.meng-editor-body-content {
  width: 100%;
  height: 100%;
  outline: none;
  border: none;
  resize: none;
  padding: 5px;
  text-align: left;
  box-sizing: border-box;
}

.meng-editor-header-ul {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  list-style: none;
}
.meng-editor-header-ul > li {
  width: 30px;
  height: 40px;
  line-height: 40px;
  text-align: center;
}
.meng-editor-header-ul > li:hover {
  /* color: #1e88e5;*/
}
.meng-editor-popup {
  /* min-width: 100px; */
  height: 100px;
  /* background: red; */
  position: absolute;
}
.meng-editor-header-li-selected {
  color: #1e88e5;
}
/* 表格 */
.insertTable {
  width: 100%;
  border-collapse: collapse;
  display: table;
  table-layout: fixed;
}
.insertTable tr td {
  border: 1px solid rgb(147, 146, 146);
  text-align: center;
}
#text_area ul {
  float: none;
  width: auto;
  list-style-type: disc;
  padding: 0 20px;
}
#text_area ul li {
  float: none;
  width: auto;
  line-height: normal;
  overflow: visible;
  list-style-type: disc;
  list-style: disc;
  padding: 0 20px;
  white-space: normal;
}
.inertImage:hover {
  box-shadow: 0px 0px 12px black;
}
.flex-row {
  display: flex;
  flex-direction: row;
}
</style>